import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'context_data.dart';

///使用方法
/**
    LoadStateLayout(
    controller: loadStateController,
    errorRetry: onRetryClick,
    emptyRetry: onEmptyClick,
    child: buildWidget(context),
    )
 */
//四种视图状态
enum LoadState { Success, Error, Loading, Empty }

class LoadStateController {
  _LoadStateLayoutState? _state;

  //当页面未绑定的时候，缓存一下，当绑定的时候，恢复一下
  LoadState? _cacheLoadState;

  void setLoadState(LoadState loadState, {ContextData? data}) {
    if (_state == null) {
      _cacheLoadState = loadState;
    }
    if (_state?.setLoadState(loadState) == true) {
      _state!.contextData = data ?? ContextData();
      _state!.setState(() {});
    }
  }

  void showLoading({ContextData? data}) {
    setLoadState(LoadState.Loading, data: data);
  }

  void showRetry({ContextData? data}) {
    setLoadState(LoadState.Error, data: data ?? ContextData(title: LoadStateLayout.load_switch_retry_title.tr, buttonText: LoadStateLayout.load_switch_retry_btn.tr));
  }

  void showContent({ContextData? data}) {
    setLoadState(LoadState.Success, data: data);
  }

  void showEmpty({ContextData? data}) {
    setLoadState(LoadState.Empty, data: data ?? ContextData(title: LoadStateLayout.load_switch_empty.tr));
  }

  /// 是否已经与控件绑定
  bool isBind() => _state != null;

  bool isLoadingCanShow() => _state?.loadingCanShow != false;

  bool isLoading() => _state?._loadState == LoadState.Loading;

  //销毁
  void dispose() {
    _state = null;
  }
}

//根据不同状态来展示不同的视图
class LoadStateLayout extends StatefulWidget {
  static const load_switch_retry_btn = "load_switch_retry_btn";
  static const load_switch_retry_title = "load_switch_retry_title";
  static const load_switch_empty = "load_switch_empty";

  //LoadStateLayout 默认使用的icon
  static Widget? Function(BuildContext, ContextData) defaultLoadStateLayoutIcon = (BuildContext context, ContextData contextData) => null;

  final Widget child; //成功视图
  final Widget? error; //空数据视图
  final Widget? empty; //错误视图
  final Widget? loading; //加载中视图
  final Widget Function(ContextData)? errorBuild; //空数据视图
  final Widget Function(ContextData)? emptyBuild; //错误视图
  final Widget Function(ContextData)? loadingBuild; //加载中视图
  final ValueChanged<ContextData>? onError; //错误事件处理
  final ValueChanged<ContextData>? onEmpty; //空数据事件处理
  final LoadStateController controller; //状态控制器

  const LoadStateLayout({
    super.key,
    required this.controller,
    required this.child,
    this.empty,
    this.error,
    this.loading,
    this.errorBuild,
    this.emptyBuild,
    this.loadingBuild,
    this.onError,
    this.onEmpty,
  });

  @override
  State createState() => _LoadStateLayoutState();
}

class _LoadStateLayoutState extends State<LoadStateLayout> {
  //页面状态
  LoadState? _loadState;

  //页面状态
  ContextData contextData = ContextData();

  // 如果成功了那么Start方法就不会显示加载中的布局
  bool loadingCanShow = true;

  //标记是否只显示加载中一次
  bool loadingShowOne = true;

  @override
  void initState() {
    super.initState();
    _bindController();
  }

  bool setLoadState(LoadState value) {
    if (value == LoadState.Loading && !loadingCanShow) {
      return false;
    }
    if (_loadState != value) {
      _loadState = value;
      return true;
    }
    return false;
  }

  @override
  void didUpdateWidget(covariant LoadStateLayout oldWidget) {
    super.didUpdateWidget(oldWidget);
    if (oldWidget.controller != widget.controller) {
      _bindController();
    }
  }

  @override
  Widget build(BuildContext context) {
    return SizedBox(
      //宽高都充满屏幕剩余空间
      width: double.infinity,
      height: double.infinity,
      child: _buildWidget,
    );
  }

  void _bindController() {
    widget.controller._state = this;
  }

  // 根据不同状态来显示不同的视图
  Widget? get _buildWidget {
    final status = _loadState ?? widget.controller._cacheLoadState ?? LoadState.Loading;
    switch (status) {
      case LoadState.Loading:
        return widget.loading ?? widget.loadingBuild?.call(contextData) ?? LoadView(contextData: contextData);
      case LoadState.Success:
        if (loadingShowOne) {
          loadingCanShow = false;
        }
        return widget.child;
      case LoadState.Error:
        loadingCanShow = true;
        return widget.error ?? widget.errorBuild?.call(contextData) ?? ErrorView(contextData: contextData, errorRetry: widget.onError);
      case LoadState.Empty:
        loadingCanShow = true;
        return widget.empty ?? widget.emptyBuild?.call(contextData) ?? NoDataView(contextData: contextData, emptyRetry: widget.onEmpty);
      }
  }

  @override
  void dispose() {
    super.dispose();
    widget.controller.dispose();
  }
}

class LoadView extends StatelessWidget {
  final ContextData contextData;

  const LoadView({super.key, required this.contextData});

  @override
  Widget build(BuildContext context) {
    return Container(
      width: double.infinity,
      height: double.infinity,
      alignment: Alignment.center,
      child: Container(
        alignment: Alignment.center,
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          crossAxisAlignment: CrossAxisAlignment.center,
          children: <Widget>[
            SizedBox(
              width: 46,
              height: 46,
              child: CircularProgressIndicator(
                valueColor: AlwaysStoppedAnimation(contextData.circleColor ?? Theme.of(context).primaryColor),
                strokeWidth: 2,
              ),
            ),
            const SizedBox(
              height: 10,
            ),
            Offstage(
              offstage: contextData.title.isEmpty,
              child: Text(
                contextData.title,
                style: TextStyle(color: contextData.titleColor, fontSize: 12),
              ),
            )
          ],
        ),
      ),
    );
  }
}

class ErrorView extends StatelessWidget {
  final ValueChanged<ContextData>? errorRetry;
  final ContextData contextData;

  const ErrorView({super.key, required this.contextData, this.errorRetry});

  @override
  Widget build(BuildContext context) {
    final imageWidget = contextData.resImage != null
        ? SizedBox(
            width: contextData.imgWidth,
            height: contextData.imgHeight,
            child: contextData.resImage,
          )
        : LoadStateLayout.defaultLoadStateLayoutIcon(context, contextData);
    return SizedBox(
        width: double.infinity,
        height: double.infinity,
        child: InkWell(
          onTap: () {
            errorRetry?.call(contextData);
          },
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              if (imageWidget != null) imageWidget,
              if (imageWidget != null) SizedBox(height: 20),
              Offstage(
                offstage: contextData.title.isEmpty,
                child: Text(
                  contextData.title,
                  style: TextStyle(color: contextData.titleColor, fontSize: 14),
                ),
              ),
              const SizedBox(height: 15),
              SizedBox(
                width: 100,
                height: 32,
                child: TextButton(
                    onPressed: () {
                      errorRetry?.call(contextData);
                    },
                    style: ButtonStyle(
                      shape: WidgetStateProperty.all<RoundedRectangleBorder>(
                        RoundedRectangleBorder(
                          borderRadius: BorderRadius.circular(16.0), // 设置圆角半径
                          side: BorderSide(
                            color: contextData.buttonStrokeColor ?? Theme.of(context).primaryColor,
                            width: 1,
                          ),
                        ),
                      ),
                    ),
                    child: Text(
                      contextData.buttonText ?? LoadStateLayout.load_switch_retry_btn.tr,
                      style: TextStyle(color: contextData.titleColor, fontSize: 12),
                    )),
              )
            ],
          ),
        ));
  }
}

class NoDataView extends StatelessWidget {
  final ValueChanged<ContextData>? emptyRetry; //无数据事件处理
  final ContextData contextData;

  const NoDataView({super.key, required this.contextData, required this.emptyRetry});

  @override
  Widget build(BuildContext context) {
    final imageWidget = contextData.resImage != null
        ? SizedBox(
            width: contextData.imgWidth,
            height: contextData.imgHeight,
            child: contextData.resImage,
          )
        : LoadStateLayout.defaultLoadStateLayoutIcon(context, contextData);
    return SizedBox(
        width: double.infinity,
        height: double.infinity,
        child: InkWell(
          onTap: () {
            emptyRetry?.call(contextData);
          },
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              if (imageWidget != null) imageWidget,
              if (imageWidget != null) SizedBox(height: 20),
              Offstage(
                offstage: contextData.title.isEmpty,
                child: Text(
                  contextData.title,
                  style: TextStyle(color: contextData.titleColor, fontSize: 14),
                ),
              ),
            ],
          ),
        ));
  }
}
